分支管理是 git 的核心功能之一,不論是在本地端、或者跨機器協作,都可以讓我們在某個支線上進行開發或測試,而不影響主線。
本篇文章將在本地端的 git 倉儲創建分支,在分支上各自形成 commit 後,觀察合併分支時會發生的兩種狀況:「順利合併」與「合併衝突」。
在一個已經經過 git init
初始化的 git 倉儲中,透過以下指令建立 file.txt
文字檔案,內容為 "Initial content"
:
echo "Initial content" > file.txt
接著把這個新建的檔案先放到預存區:
git add file.txt
再建立第一個 commit:
git commit -m "Initial commit"
現在我們在 main
分支上已經有雜湊碼為 deb6e91...
的 commit:
現在我們以 git branch
指令,建立 featureA
分支:
git branch featureA
再用一樣的 git branch
指令,建立 featureB
分支:
git branch featureB
現在我們以 git branch
觀察,可發現目前有 main
、featureA
與 featureB
三個分支:
main
分支打星號並顯示綠色,且右上角的藍色括弧也是寫 (main)
,表示我們現在在 main
分支上,可用下列指令切換到 featureA
分支:
git switch featureA
以 git branch
指令確認,發現變成 featureA
打星號且變綠色、最右邊的藍色括弧也變成 featureA
,表示目前在 featureA
分支上:
同理,也能夠過以下指令,切換到 featureB
分支上:
git switch featureB
再以 git branch
檢查確認:
在合併分支前,我們先以 git switch
切換到 featureA
分支:
git switch featureA
接著在這個分支上建立一個名為 file.txt
的檔案,內容為 "Feature A work"
:
echo "Feature A work" > file.txt
把 file.txt
加到預存區:
git add file.txt
再為其建立一個 commit:
git commit -m "Add Feature A work"
這時透過 git log
觀察,可發現 805ba26...
這個 commit 只在 featureA
分支而不在 main
分支上:
現在我們要把 805ba26...
合併到 main
分支上。
首先切換到 main
分支:
git switch main
再用 git merge
指令合併:
git merge featureA
合併之後透過 git log
指令檢查,可發現在 main
分支與 featureA
分支都有 805ba26...
這個 commit,而 featureB
分支上依然只有 deb6e91...
這個舊的 commit:
現在我們切到 featureB
分支:
git switch featureB
在 featureB
分支上創建同樣名為 file.txt
檔案,但內容為 "Feature B conflicting line"
:
echo "Feature B conflicting line" > file.txt
一樣把這裡的 file.txt
放到預存區:
git add file.txt
再形成新的 commit:
git commit -m "Add conflicting change from featureB"
使用 git log
指令檢查,發現 featureB
分支有 339a1be...
與 deb6e91...
兩個 commit、featureA
與 main
分支則是剛剛看到的 805ba26...
與 deb6e91...
兩個 commit:
這時如果切回去 main
分支:
git switch main
再把 featureB
分支合併過來:
git merge featureB
會發生什麼事呢?
來看看終端機:
再來看看編輯器:
這種狀況稱為「合併衝突(merge conflict)」,源於合併時,兩個分支在同一檔案的同樣行別發生改變,這時有三種解決方式:
main
)」的版本為準。featureB
)」的版本為準。我們依照需求在編輯器點選其中一個之後,把 file.txt
放進預存區:
git add file.txt
再形成新 commit:
git commit -m "Merge featureB into main"
以 git log
檢查,可發現在 main
分支上多了一個代表把 featureB
分支合併進來的新 commit 9b7b77f...
:
現在我們換個方式調整分支結構。
先輸入以下指令,退回合併前的狀態:
git reset --hard HEAD~1
接著切換到 featureB
分支上:
git switch featureB
然後把這個 featureB
分支「接」上 main
分支:
git rebase main
衝突再度發生,原因跟剛剛一樣,都是兩分支同樣在 file.txt
的同樣行別發生變化:
這次一樣會跑出 Accept Current Change
、Accept Incoming Change
、Accept Both Changes
三種選項,依照需求選擇一個之後,把檔案放進預存區:
git add file.txt
接著繼續做 rebase:
git rebase --continue
這時可能跳出 vim 之類的編輯器,要我們編輯 rebase 的 commit 訊息,編輯好訊息並關閉編輯器後,即完成 rebase:
之後我們會細看分支新增、刪除、轉換,還有合併衝突的處理,如果對於上述用上層指令操作仍不熟悉,可以先參考以下由高見龍老師撰寫的公開文章複習:
如果跳出 vim 編輯器不會處理,則可以參考:
以上層的瓷器指令要管理分支時,主要會用到以下指令:
git branch
:用來新增與查看分支。git switch
:切換分支,跟以前使用的 git checkout
相比,功能更為專一。git merge
:合併分支。git rebase
:「看似」把某分支基底接到另一分支上,可想成是另一種合併分支的方式。若在合併的兩分支同一檔案的相同區塊做出不一樣的更改,則在 git merge
與 git rebase
時會產生衝突,需要另外去解。